// Learn TypeScript:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html

import Debuger from "../utils/Debuger";
import { Agent } from "./libs/Agent";
import { RVOSimulator } from "./libs/RVOSimulator";
import ObstacleComp from "./ObstacleComp";
import RvoMoveComp from "./RvoMoveComp";

const { ccclass, property } = cc._decorator;

@ccclass
export default class RvoScene extends cc.Component {
    @property(cc.Node)
    cocos: cc.Node = null;

    @property(cc.Node)
    creator: cc.Node = null;

    @property(cc.Node)
    obstacle: cc.Node = null;

    private _debugRvo: boolean = false;
    private _cocosStartPos: cc.Vec2[] = [];
    private _creatorStartPos: cc.Vec2[] = [];
    start() {
        //初始化cocos
        this.cocos.children.forEach((element, index) => {
            this._cocosStartPos.push(element.getPosition());
            if (!element.active) return;
            let rvoComp = element.addComponent(RvoMoveComp);
            let destNode = this.creator.children[this.creator.children.length - index - 1];
            cc.Vec2.set(rvoComp.destPosition, destNode.x, destNode.y);
        });

        //初始化creator
        this.creator.children.forEach((element, index) => {
            this._creatorStartPos.push(element.getPosition());
            if (!element.active) return;
            let rvoComp = element.addComponent(RvoMoveComp);
            let destNode = this.cocos.children[this.cocos.children.length - index - 1];
            cc.Vec2.set(rvoComp.destPosition, destNode.x, destNode.y);
        });

        //初始化障碍物  
        this.obstacle.children.forEach(element => {
            element.addComponent(ObstacleComp);
        });
    }

    protected lateUpdate(dt: number): void {
        RVOSimulator.getInstance().doStep(dt);

        let graphics = Debuger.getGraphcis();
        graphics.clear();
        if (this._debugRvo) {
            this.cocos.children.forEach(element => {
                let rvoComp = element.getComponent(RvoMoveComp);
                if (rvoComp && rvoComp.agent) {
                    this.drawAgent(rvoComp.agent, cc.Color.GREEN);
                }
            });

            this.creator.children.forEach(element => {
                let rvoComp = element.getComponent(RvoMoveComp);
                if (rvoComp && rvoComp.agent) {
                    this.drawAgent(rvoComp.agent, cc.Color.RED);
                }
            });
        }
    }

    clickDebugRvo() {
        this._debugRvo = !this._debugRvo;
    }

    clickReset() {
        this.cocos.children.forEach((element, index) => {
            element.setPosition(this._cocosStartPos[index]);
            if (!element.active) return;
            let rvoComp = element.getComponent(RvoMoveComp);
            rvoComp.syncPositionToAgent();
            rvoComp.destPosition.set(this._creatorStartPos[this.creator.children.length - index - 1]);
        });

        this.creator.children.forEach((element, index) => {
            element.setPosition(this._creatorStartPos[index]);
            if (!element.active) return;
            let rvoComp = element.getComponent(RvoMoveComp);
            rvoComp.syncPositionToAgent();
            rvoComp.destPosition.set(this._cocosStartPos[this.cocos.children.length - index - 1]);
        });
    }

    drawAgent(agent: Agent, color: cc.Color = cc.Color.WHITE) {
        let graphics = Debuger.getGraphcis();
        graphics.fillColor = color;
        graphics.circle(agent.position_.x_, agent.position_.y_, agent.radius_);
        graphics.fill();
    }
}
